home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.000 / crossfir / crossfire-0.92.4.client / item.c < prev    next >
C/C++ Source or Header  |  1996-04-21  |  10KB  |  421 lines

  1. /*
  2.     CrossFire, A Multiplayer game for X-windows
  3.  
  4.     Copryight (C) 1994 Mark Wedel
  5.     Copyright (C) 1992 Frank Tore Johansen
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.     The author can be reached via e-mail to master@rahul.net
  22. */
  23.  
  24. #include <ctype.h>    /* needed for isdigit */
  25. #include <includes.h>    /* prototypes most standard functions */
  26. #include <item.h>
  27.  
  28. static item *free_items;    /* the list of free (unused) items */
  29. static item *player, *map;    /* these lists contains rest of items */
  30.                 /* player = pl->ob, map = pl->below */
  31.  
  32. #define NROF_ITEMS 50        /* how many items are reserved initially */
  33.                 /* for the item spool */
  34. /*
  35.  *  new_item() returns pointer to new item which
  36.  *  is allocated and initialized correctly
  37.  */
  38. static item *new_item () 
  39. {
  40.     item *op = malloc (sizeof(item));
  41.  
  42.     if (! op) 
  43.     exit(0);
  44.  
  45.     op->next = op->prev = NULL;
  46.     copy_name (op->name, "");
  47.     op->inv = NULL;
  48.     op->env = NULL;
  49.     op->tag = 0;
  50.     op->face = 0;
  51.     op->weight = 0;
  52.     op->magical = op->cursed = op->damned = 0;
  53.     op->unpaid = op->locked = op->applied = 0;
  54.     return op;
  55. };
  56.  
  57. /*
  58.  *  alloc_items() returns pointer to list of allocated objects
  59.  */
  60. static item *alloc_items (int nrof) {
  61.     item *op, *list;
  62.     int i;
  63.  
  64.     list = op = new_item();
  65.  
  66.     for (i=1; i<nrof; i++) {
  67.     op->next = new_item();
  68.     op->next->prev = op;
  69.     op = op->next;
  70.     }
  71.     return list;
  72. }
  73.  
  74. /*
  75.  *  free_items() frees all allocated items from list
  76.  */
  77. void free_all_items (item *op) {
  78.     item *tmp;
  79.  
  80.     while (op) {
  81.     if (op->inv)
  82.         free_all_items (op->inv);  
  83.     tmp = op->next;
  84.     free(op);
  85.     op = tmp;
  86.     }
  87. }
  88.  
  89. /*
  90.  *  Recursive function, used by locate_item()
  91.  */
  92. static item *locate_item_from_item (item *op, sint32 tag)
  93. {
  94.     item *tmp;
  95.  
  96.     for (; op; op=op->next)
  97.     if (op->tag == tag)
  98.         return op;
  99.     else if (op->inv && (tmp = locate_item_from_item (op->inv, tag)))
  100.         return tmp;
  101.  
  102.     return NULL;
  103. }
  104.  
  105. /*
  106.  *  locate_item() returns pointer to the item which tag is given 
  107.  *  as parameter or if item is not found returns NULL
  108.  */
  109. item *locate_item (sint32 tag)
  110. {
  111.     item *op;
  112.  
  113.     if (tag == 0)
  114.     return map;
  115.  
  116.     if ((op=locate_item_from_item(map->inv, tag)) != NULL)
  117.     return op;
  118.     if ((op=locate_item_from_item(player, tag)) != NULL)
  119.     return op;
  120.  
  121.     return NULL;
  122. }
  123.  
  124. /*
  125.  *  remove_item() inserts op the the list of free items
  126.  *  Note that it don't clear all fields in item
  127.  */
  128. void remove_item (item *op) 
  129. {
  130.     if (!op) return;
  131.     op->env->inv_updated = 1;
  132.     /* Do we really want to do this? */
  133.     if (op->inv)
  134.     remove_item_inventory (op);
  135.  
  136.     if (op->prev) {
  137.     op->prev->next = op->next;
  138.     } else {
  139.     op->env->inv = op->next;
  140.     }
  141.     if (op->next) {
  142.     op->next->prev = op->prev;
  143.     }
  144.  
  145.     /* add object to a list of free objects */
  146.     op->next = free_items;
  147.     if (op->next != NULL)
  148.     op->next->prev = op;
  149.     free_items = op;
  150.     op->prev = NULL;
  151.     op->env = NULL;
  152.     op->tag = 0;
  153. }
  154.  
  155. /*
  156.  *  remove_item_inventory() recursive frees items inventory
  157.  */
  158. void remove_item_inventory (item *op)
  159. {
  160.     op->inv_updated = 1;
  161.     while (op->inv)
  162.     remove_item (op->inv);
  163. }
  164.  
  165. /*
  166.  *  add_item() adds item op to end of the inventory of item env
  167.  */
  168. static void add_item (item *env, item *op) 
  169. {
  170.     item *tmp;
  171.     
  172.     for (tmp = env->inv; tmp && tmp->next; tmp=tmp->next)
  173.     ;
  174.  
  175.     op->next = NULL;
  176.     op->prev = tmp;
  177.     op->env = env;
  178.  
  179.     if (!tmp) {
  180.     env->inv = op;
  181.     } else {
  182.     if (tmp->next)
  183.         tmp->next->prev = op;
  184.     tmp->next = op;
  185.     }
  186. }
  187.  
  188. /*
  189.  *  create_new_item() returns pointer to a new item, inserts it to env 
  190.  *  and sets its tag field and clears locked flag (all other fields
  191.  *  are unitialized and may contain random values)
  192.  */
  193. item *create_new_item (item *env, sint32 tag)
  194. {
  195.     item *op;
  196.  
  197.     if (!free_items)
  198.     free_items = alloc_items (NROF_ITEMS);
  199.  
  200.     op = free_items;
  201.     free_items = free_items->next;
  202.     if (free_items)
  203.     free_items->prev = NULL;
  204.  
  205.     op->tag = tag;
  206.     op->locked = 0;
  207.     add_item (env, op);
  208.     return op;
  209. }
  210.  
  211. #if 0
  212. /*
  213.  *  parse different flags (applied/worn/etc), but not flags which are
  214.  *  part of a name (e.g. 'ring (Str +1)')
  215.  *  (TODO: Insert strings to a configuration file)
  216.  */
  217. static void get_flags (item *op)
  218. {
  219.     char *s1, *s2, buf[256];
  220.  
  221.     s1 = op->name;
  222.     buf[0] = 0;
  223.     op->flags[0] = 0;
  224.     op->was_open = op->open;
  225.     op->open = 0;
  226.     op->applied = op->unpaid = op->magical = op->damned = op->cursed = 0;
  227.  
  228.     while ((s2=strchr(s1, ' ')) != NULL) {
  229.     strncat (buf, s1, s2 - s1);
  230.     s1 = s2;
  231.     if (*(s2+1) == '(') {
  232.         if (strncmp (s2, " (magic)", 8) == 0) {
  233.         op->magical = 1;
  234.         strcat (op->flags, " (magic)");
  235.         s1 += 8;
  236.         } else if (strncmp (s2, " (worn)", 7) == 0) {
  237.         op->applied = 1;
  238.         strcat (op->flags, " (worn)");
  239.         s1 += 7;
  240.         } else if (strncmp (s2, " (wielded)", 10) == 0) {
  241.         op->applied = 1;
  242.         strcat (op->flags, " (wielded)");
  243.         s1 += 10;
  244.         } else if (strncmp (s2, " (damned)", 9) == 0) {
  245.         op->damned = 1;
  246.         strcat (op->flags, " (damned)");
  247.         s1 += 9;
  248.         } else if (strncmp (s2, " (cursed)", 9) == 0) {
  249.         op->cursed = 1;
  250.         strcat (op->flags, " (cursed)");
  251.         s1 += 9;
  252.         } else if (strncmp (s2, " (readied)", 10) == 0) {
  253.         op->applied = 1;
  254.         strcat (op->flags, " (readied)");
  255.         s1 += 10;
  256.         } else if (strncmp (s2, " (active)", 9) == 0) {
  257.         op->applied = 1;
  258.         strcat (op->flags, " (active)");
  259.         s1 += 9;
  260.         } else if (strncmp (s2, " (unpaid)", 9) == 0) {
  261.         op->unpaid = 1;    
  262.         strcat (op->flags, " (unpaid)");
  263.         s1 += 9;
  264.         } else if (strncmp (s2, " (open)", 7) == 0) {
  265.         op->open = 1;
  266.         strcat (op->flags, " (open)");
  267.         s1 += 7;
  268.         } else {
  269.         strncat (buf, s2, 1);
  270.         s1 += 1;
  271.         }
  272. #if 1 /* checking locked, but this really belongs to client size */
  273.     } else if (strncmp (s2, " *", 2) == 0) {
  274.         op->locked = 1;
  275.         strcat (op->flags, " *");
  276.         s1 += 2;
  277. #endif
  278.     } else {
  279.         strncat (buf, s2, 1);
  280.         s1 += 1;
  281.     }
  282.     }
  283.     if (*s1)
  284.     strcat (buf, s1);
  285.     copy_name (op->name, buf);
  286. }
  287. #else
  288.  
  289. /*
  290.  *  Hardcoded now, server could send these at initiation phase.
  291.  */
  292. enum {a_none, a_readied, a_wielded, a_worn, a_active, a_applied};
  293. static char *apply_string[] = {
  294.     "", " (readied)", " (wielded)", " (worn)", " (active)", " (applied)"
  295. };
  296.  
  297. #define F_APPLIED    0x000F
  298. #define F_LOCATION    0x00F0
  299. #define F_CLEAR_INV    0x0100
  300. #define F_UNPAID    0x0200
  301. #define F_MAGIC        0x0400
  302. #define F_CURSED    0x0800
  303. #define F_DAMNED    0x1000
  304. #define F_OPEN        0x2000
  305. #define F_NOPICK    0x4000
  306.  
  307. static void set_flag_string (item *op)
  308. {
  309.     op->flags[0] = 0;
  310.  
  311.     if (op->locked) 
  312.     strcat (op->flags, " *");
  313.     if (op->apply_type) {
  314.     if (op->apply_type <= sizeof (apply_string) / sizeof(apply_string[0])) 
  315.         strcat (op->flags, apply_string[op->apply_type]);
  316.     else 
  317.         strcat (op->flags, " (undefined)");
  318.     }
  319.     if (op->open)
  320.     strcat (op->flags, " (open)");
  321.     if (op->damned)
  322.     strcat (op->flags, " (damned)");
  323.     if (op->cursed)
  324.     strcat (op->flags, " (cursed)");
  325.     if (op->magical)
  326.     strcat (op->flags, " (magic)");
  327.     if (op->unpaid)
  328.     strcat (op->flags, " (unpaid)");
  329. }
  330.  
  331. static void get_flags (item *op, uint16 flags)
  332. {
  333.     op->was_open = op->open;
  334.     op->open    = flags & F_OPEN    ? 1 : 0;
  335.     op->damned  = flags & F_DAMNED  ? 1 : 0;
  336.     op->cursed  = flags & F_CURSED  ? 1 : 0;
  337.     op->magical = flags & F_MAGIC   ? 1 : 0;
  338.     op->unpaid  = flags & F_UNPAID  ? 1 : 0;
  339.     op->applied = flags & F_APPLIED ? 1 : 0;
  340.     op->apply_type = flags & F_APPLIED;
  341.     set_flag_string(op);
  342. }
  343. #endif
  344.  
  345. /*
  346.  *  get_nrof() functions tries to get number of items from the item name
  347.  */
  348. static sint32 get_nrof(char *name) 
  349. {
  350.     static char *numbers[21] = {
  351.     "no ","a ","two ","three ","four ","five ","six ","seven ","eight ",
  352.     "nine ","ten ","eleven ","twelve ","thirteen ","fourteen ","fifteen ",
  353.     "sixteen ","seventeen ","eighteen ","nineteen ","twenty "
  354.     };
  355.     static char *numbers_10[10] = {
  356.     "zero ","ten ","twenty ","thirty ","fourty ","fifty ","sixty ",
  357.     "seventy ","eighty ","ninety "
  358.     };
  359.     sint32 nrof = 0;
  360.     int i;
  361.  
  362.     if (isdigit (*name))
  363.     nrof = atol (name);
  364.     else if (strncmp (name, "a ", 2) == 0 || strncmp (name, "an ", 3) == 0)
  365.     nrof = 1;
  366.     else {
  367.     for (i=1; i<sizeof(numbers)/sizeof(numbers[0]); i++)
  368.         if (strncmp (name, numbers[i], strlen (numbers[i])) == 0) {
  369.         nrof = i;
  370.         break;
  371.         }
  372.     if ( !nrof ) {
  373.         for (i=1; i<sizeof(numbers_10)/sizeof(numbers_10[0]); i++)
  374.         if (strncmp(name, numbers_10[i], strlen(numbers_10[i])) == 0) {
  375.             nrof = i * 10;
  376.             break;
  377.         }
  378.     }
  379.     }
  380.     
  381.     return nrof ? nrof : 1; 
  382. }
  383.  
  384. void set_item_values (item *op, char *name, sint32 weight, uint16 face, 
  385.               uint16 flags) 
  386. {
  387.     if (!op) {
  388.     printf ("Error in set_item_values(): item pointer is NULL.\n");
  389.     return;
  390.     }
  391.     copy_name (op->name, name);
  392.     op->env->inv_updated = 1;
  393.     op->nrof = get_nrof(name);
  394.     op->weight = (float) weight / 1000;
  395.     op->face = face;
  396.     get_flags (op, flags);
  397. }
  398.  
  399. void toggle_locked (item *op)
  400. {
  401.     if (op->env->tag == 0)
  402.     return;    /* if item is on the ground, don't lock it */
  403.     op->locked = !op->locked;
  404.     op->env->inv_updated = 1;
  405.     set_flag_string (op);
  406. }
  407.  
  408. item *player_item ()
  409. {
  410.     player = new_item(); 
  411.     return player;
  412. }
  413.  
  414. item *map_item ()
  415. {
  416.     map = new_item();
  417.     map->weight = -1;
  418.     return map;
  419. }
  420.  
  421.